package com.stt.experiment.websocket.action.dispatcher.support;

import com.stt.experiment.websocket.action.dispatcher.annotation.ReqAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.core.env.Environment;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;

public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware {
    private static final Logger log = LoggerFactory.getLogger(ServiceAnnotationBeanPostProcessor.class);
    private final Set<String> packagesToScan;
    private Environment environment;

    public ServiceAnnotationBeanPostProcessor(String... packagesToScan) {
        this((Collection) Arrays.asList(packagesToScan));
    }

    public ServiceAnnotationBeanPostProcessor(Collection<String> packagesToScan) {
        this((Set)(new LinkedHashSet(packagesToScan)));
    }

    public ServiceAnnotationBeanPostProcessor(Set<String> packagesToScan) {
        this.packagesToScan = packagesToScan;
    }

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        Set<String> resolvedPackagesToScan = this.resolvePackagesToScan(this.packagesToScan);
        if(!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
            this.registerReqActionBeans(resolvedPackagesToScan, registry);
        } else if(log.isWarnEnabled()) {
            log.warn("packagesToScan is empty , ReqActionBean registry will be ignored!");
        }

    }

    private Set<String> resolvePackagesToScan(Set<String> packagesToScan) {
        Set<String> resolvedPackagesToScan = new LinkedHashSet(packagesToScan.size());
        Iterator var3 = packagesToScan.iterator();

        while(var3.hasNext()) {
            String packageToScan = (String)var3.next();
            if(StringUtils.hasText(packageToScan)) {
                String resolvedPackageToScan = this.environment.resolvePlaceholders(packageToScan.trim());
                resolvedPackagesToScan.add(resolvedPackageToScan);
            }
        }

        return resolvedPackagesToScan;
    }

    private void registerReqActionBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
        ActionClassPathBeanDefinitionScanner scanner = new ActionClassPathBeanDefinitionScanner(registry);
        BeanNameGenerator beanNameGenerator = this.resolveBeanNameGenerator(registry);
        scanner.setBeanNameGenerator(beanNameGenerator);
        scanner.addIncludeFilter(new AnnotationTypeFilter(ReqAction.class));
        Iterator var5 = packagesToScan.iterator();

        while(var5.hasNext()) {
            String packageToScan = (String)var5.next();
            scanner.scan(new String[]{packageToScan});
        }

    }

    private BeanNameGenerator resolveBeanNameGenerator(BeanDefinitionRegistry registry) {
        BeanNameGenerator beanNameGenerator = null;
        if(registry instanceof SingletonBeanRegistry) {
            SingletonBeanRegistry singletonBeanRegistry = (SingletonBeanRegistry)SingletonBeanRegistry.class.cast(registry);
            beanNameGenerator = (BeanNameGenerator)singletonBeanRegistry.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
        }

        if(beanNameGenerator == null) {
            if(log.isInfoEnabled()) {
                log.info("BeanNameGenerator bean can't be found in BeanFactory with name [org.springframework.context.annotation.internalConfigurationBeanNameGenerator]");
                log.info("BeanNameGenerator will be a instance of " + AnnotationBeanNameGenerator.class.getName() + " , it maybe a potential problem on bean name generation.");
            }

            beanNameGenerator = new AnnotationBeanNameGenerator();
        }

        return (BeanNameGenerator)beanNameGenerator;
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}

